/************************************************************************
* mapgen_terrain.c
* voxelands - 3d voxel world sandbox game
* Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>
************************************************************************/

#include "common.h"

#define _MAPGEN_LOCAL
#include "map.h"
#include "content_block.h"

typedef struct mg_offsets_s {
	int x;
	int y;
	int z;
	int cx;
	int cy;
	int cz;
} mg_offsets_t;

static block_t terrain_blocks[32][288][32];
static int terrain_heights[32][32];
static int terrain_genheights[32][32];
static mg_offsets_t terrain_offsets[72] = {
	{16,0,16, 0,-80,0},
	{0,0,16, -16,-80,0},
	{16,0,0, 0,-80,-16},
	{0,0,0, -16,-80,-16},
	{16,16,16, 0,-64,0},
	{0,16,16, -16,-64,0},
	{16,16,0, 0,-64,-16},
	{0,16,0, -16,-64,-16},
	{16,32,16, 0,-48,0},
	{0,32,16, -16,-48,0},
	{16,32,0, 0,-48,-16},
	{0,32,0, -16,-48,-16},
	{16,48,16, 0,-32,0},
	{0,48,16, -16,-32,0},
	{16,48,0, 0,-32,-16},
	{0,48,0, -16,-32,-16},
	{16,64,16, 0,-16,0},
	{0,64,16, -16,-16,0},
	{16,64,0, 0,-16,-16},
	{0,64,0, -16,-16,-16},
	{16,80,16, 0,0,0},
	{0,80,16, -16,0,0},
	{16,80,0, 0,0,-16},
	{0,80,0, -16,0,-16},
	{16,96,16, 0,16,0},
	{0,96,16, -16,16,0},
	{16,96,0, 0,16,-16},
	{0,96,0, -16,16,-16},
	{16,112,16, 0,32,0},
	{0,112,16, -16,32,0},
	{16,112,0, 0,32,-16},
	{0,112,0, -16,32,-16},
	{16,128,16, 0,48,0},
	{0,128,16, -16,48,0},
	{16,128,0, 0,48,-16},
	{0,128,0, -16,48,-16},
	{16,144,16, 0,64,0},
	{0,144,16, -16,64,0},
	{16,144,0, 0,64,-16},
	{0,144,0, -16,64,-16},
	{16,160,16, 0,80,0},
	{0,160,16, -16,80,0},
	{16,160,0, 0,80,-16},
	{0,160,0, -16,80,-16},
	{16,176,16, 0,96,0},
	{0,176,16, -16,96,0},
	{16,176,0, 0,96,-16},
	{0,176,0, -16,96,-16},
	{16,192,16, 0,112,0},
	{0,192,16, -16,112,0},
	{16,192,0, 0,112,-16},
	{0,192,0, -16,112,-16},
	{16,208,16, 0,128,0},
	{0,208,16, -16,128,0},
	{16,208,0, 0,128,-16},
	{0,208,0, -16,128,-16},
	{16,224,16, 0,144,0},
	{0,224,16, -16,144,0},
	{16,224,0, 0,144,-16},
	{0,224,0, -16,144,-16},
	{16,240,16, 0,160,0},
	{0,240,16, -16,160,0},
	{16,240,0, 0,160,-16},
	{0,240,0, -16,160,-16},
	{16,256,16, 0,176,0},
	{0,256,16, -16,176,0},
	{16,256,0, 0,176,-16},
	{0,256,0, -16,176,-16},
	{16,272,16, 0,192,0},
	{0,272,16, -16,192,0},
	{16,272,0, 0,192,-16},
	{0,272,0, -16,192,-16}
};

/* generate a ground-level region (-80 to 208) */
void mapgen_terrain(pos_t *p)
{
	int x;
	int y;
	int z;
	int i;
	int u;
	block_t *b;
	block_t *cb;
	pos_t cp;
	chunk_t *ch;

	int h = 1+80;

	for (x=0; x<32; x++) {
		for (z=0; z<32; z++) {
			h = noise_height(p->x+x,p->z+z);
			terrain_heights[x][z] = h;
			terrain_genheights[x][z] = h;
			h += 80;
			for (y=0; y<288; y++) {
				b = &terrain_blocks[x][y][z];
				b->param1 = 0;
				b->param2 = 0;
				b->param3 = 0;
				if (y > h) {
					b->content = CONTENT_AIR;
				}else if (y < (h-5)) {
					b->content = CONTENT_STONE;
				}else if (y == h && y>79) {
					b->content = CONTENT_GRASS;
				}else{
					b->content = CONTENT_MUD;
				}
			}
		}
	}

	for (i=0; i<72; i++) {
		cp.x = p->x+terrain_offsets[i].cx;
		cp.y = p->y+terrain_offsets[i].cy;
		cp.z = p->z+terrain_offsets[i].cz;
		ch = mapgen_create_chunk(&cp);
		u = 0;
		for (x=0; x<16; x++) {
			for (y=0; y<16; y++) {
				for (z=0; z<16; z++) {
					b = &terrain_blocks[x+terrain_offsets[i].x][y+terrain_offsets[i].y][z+terrain_offsets[i].z];
					cb = &ch->blocks[x][y][z];
					cb->content = b->content;
					cb->param1 = b->param1;
					cb->param2 = b->param2;
					cb->param3 = b->param3;
					if (cb->content != CONTENT_AIR)
						u++;
				}
			}
		}

		ch->state &= ~CHUNK_STATE_UNGENERATED;
		if (!u)
			ch->state |= CHUNK_STATE_EMPTY;
		if (u == 4096)
			ch->state |= CHUNK_STATE_UNDERGROUND;

		map_add_chunk(ch);
	}
}
